/**
 * @file 08-generics.ts
 *
 * 1.3.9 使用泛型，将相同的代码用于不同的类型
 *
 * 利用队列说明泛型的使用
 * 
 * 使用接口说明泛型如何去调用一个接口函数
 */

/**
 * 实现了一个整形数据的队列
 * 
 * 队列： 先进先出
 * 栈： 先进后出
 */
class QueueOfInt {
    private queue: number[] = [];

    public Push(value: number): void {
        this.queue.push(value);
    }

    public Pop(): number | undefined {
        return this.queue.shift();
    }
}

class QueueOfString {
    private queue: string[] = [];

    public Push(value: string): void {
        this.queue.push(value);
    }

    public Pop(): string | undefined {
        return this.queue.pop();
    }
}

class Queue<T>{
    private queue: T[] = [];

    public Push(value: T): void {
        this.queue.push(value);
    }

    public Pop(): T | undefined {
        return this.queue.shift();
    }
}


//#region 样例代码验证

let queue: Queue<number> = new Queue<number>()
queue.Push(1);
queue.Push(2);

console.log(queue.Pop())
console.log(queue.Pop())

let queuestring: Queue<string> = new Queue<string>()
queuestring.Push("1");
queuestring.Push("2");

console.log(queuestring.Pop())
console.log(queuestring.Pop())
//#endregion

// 这样的代码不可以
// interface IStream {
//     ReadStream(): Int8Array; // 字节数组
// }

// class Data<T>{
//     ReadStrean(stream: T) {
//         let output = stream.ReadStream();
//     }
// }


interface IStream {
    ReadStream(): Int8Array; // Array of bytes
}

class Data<T extends IStream> {

    ReadStream(stream: T) {
        let output = stream.ReadStream();
        console.log(output);
    }
}

// Method level constraint:
// class Data {
//     ReadStream<T extends IStream>(stream : T) {
//         let output = stream.ReadStream();
//         console.log(output.byteLength);
//     }
// }

class WebStream implements IStream {
    ReadStream(): Int8Array {
        let array: Int8Array = new Int8Array(8);

        for (let index: number = 0; index < array.length; index++) {
            array[index] = index + 3;
        }

        return array;
    }
}

class DiskStream implements IStream {
    ReadStream(): Int8Array {
        let array: Int8Array = new Int8Array(20);

        for (let index: number = 0; index < array.length; index++) {
            array[index] = index + 3;
        }

        return array;
    }
}

const webData = new Data<WebStream>();
const diskData = new Data<DiskStream>();

webData.ReadStream(new WebStream());
diskData.ReadStream(new DiskStream());